package com.wstuo.common.security.dao;

import java.sql.SQLException;
import java.util.List;
import java.util.Set;

import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.util.StringUtils;

import com.wstuo.common.dao.BaseDAOImplHibernate;
import com.wstuo.common.exception.ApplicationException;
import com.wstuo.common.security.entity.Resource;
import com.wstuo.common.util.CollectionUtils;

/**
 * 资源DAO.
 * 
 * @author will
 */
public class ResourceDAO extends BaseDAOImplHibernate<Resource> implements IResourceDAO {

	/**
	 * 根据资源地址查找资源.
	 * 
	 * @param requestUrl
	 *            资源地址 String
	 * @return 资源对象 Resource
	 */
	@SuppressWarnings("unchecked")
	public Resource findByResUrl(String requestUrl) {
		Resource resource = null;
		final DetachedCriteria dc = DetachedCriteria.forClass(Resource.class);
		dc.setFetchMode( "roles", FetchMode.EAGER );
		if (StringUtils.hasText(requestUrl)) {
			dc.add(Restrictions.eq("resUrl", requestUrl));
		}
		
//		Criteria c = dc.getExecutableCriteria(getSession());
//		c.setCacheRegion("resource");
//		c.setCacheable(true);
//		List<Resource> res = c.list();
		//getSession().close();
		List<Resource> res = getHibernateTemplate().executeFind(new HibernateCallback<List<Resource>>(){
			public List<Resource> doInHibernate(Session session)
					throws HibernateException, SQLException {
				Criteria c = dc.getExecutableCriteria(session);
				c.setCacheRegion("resource");
				c.setCacheable(true);
				List<Resource> res = c.list();
				if (CollectionUtils.hasUniqueObject(res)) {
					Resource resource = res.get(0);
					resource.getRoles().size();
				}
				return res;
			}
		});
		
//		List<Resource> res = getHibernateTemplate().findByCriteria(dc);

		if (CollectionUtils.hasUniqueObject(res)) {
			resource = res.get(0);
		}
		return resource;
	}

	/**
	 * 编辑，查找相同的数据.
	 * 
	 * @param resName
	 * @param resCode
	 * @param resUrl
	 * @param id
	 */
	@SuppressWarnings("unchecked")
	public void findExists2(String resName, String resCode, String resUrl, Long id) {
		//名字可以重复,资源不重复就行
//		if (resName != null) {
//			List<Object> obj = super.getHibernateTemplate().find(" from Resource rs where rs.resName='" + resName + "' and rs.resNo!=" + id);
//			if (!obj.isEmpty()) {
//				throw new ApplicationException("ERROR_RES_NAME_EXISTS");
//			}
//		}
		if (resCode != null) {

			List<Object> obj = super.getHibernateTemplate().find(" from Resource rs where rs.resCode='" + resCode + "' and rs.resNo!=" + id);
			if (!obj.isEmpty()) {
				throw new ApplicationException("ERROR_RES_CODE_EXISTS");
			}
		}
		if (resUrl != null) {
			List<Object> obj = super.getHibernateTemplate().find(" from Resource rs where rs.resUrl='" + resUrl + "' and rs.resNo!=" + id);
			if (!obj.isEmpty()) {
				throw new ApplicationException("ERROR_RES_URL_EXISTS");
			}
		}
	}

	// 最迟的编号
	public static Long latesResNo = 0L;

	/**
	 * 直接设置编号
	 * 
	 * @param no
	 */
	public void setLatesResNo(Long no) {

		synchronized (this) {

			latesResNo = no;
		}
	}

	/**
	 * 累加资源编号.
	 */
	public void increment() {

		synchronized (this) {

			latesResNo += 1;
		}

	}

	/**
	 * 查询最后一个Res No
	 * 
	 * @return late res no
	 */
	public Long getLatesResNo() {

		synchronized (this) {
			return latesResNo;
		}
	}

	/**
	 * 查询下一个资源编号
	 * 
	 * @return next res no
	 */
	public Long getNextResNo() {

		Long v = 1L;
		final String hql = "select max(r.resNo) from Resource r";
		List list = getHibernateTemplate().find(hql);

		if (list != null && list.size() > 0) {
			Number n = (Number) list.get(0);
			if (n != null) {
				v = n.longValue() + 1;
			}
		}

		return v;

	}

	/**
	 * 重写SAVE方法.
	 * 
	 * @param entity
	 */
	@Override
	public void save(Resource entity) {

		if (entity.getResNo() == null || entity.getResNo() == 0) {
			entity.setResNo(getLatesResNo());

		} else {

			if (entity.getResNo() > getLatesResNo()) {

				setLatesResNo(entity.getResNo());
			}

		}
		super.save(entity);
		increment();// 自增1.

	}
	/**
	 * 重写merge方法.
	 * 
	 * @param entity
	 * @return Resource
	 */
	@Override
	public Resource merge(Resource entity) {

		if (entity.getResNo() != null) {
			if (entity.getResNo() >= getLatesResNo()) {
				setLatesResNo(entity.getResNo() + 1);
			}
		} else {
			increment();// 自增1.
		}

		return super.merge(entity);
	}
	/**
	 * 根据ResourceCode查询Resources
	 * @param ResourceCode
	 * @param roleCodes
	 * @return List<Resource>
	 */
	public List<Resource> findResourcesByResourceCode(String resourceCode,List<String> roleCodes){
		final DetachedCriteria dc = DetachedCriteria.forClass(Resource.class);
		dc.createAlias("roles", "rl");
		if(roleCodes!=null&&roleCodes.size()>0){
			dc.add(Restrictions.in("rl.roleCode", roleCodes));
		}
		if(StringUtils.hasText(resourceCode)){
			dc.add(Restrictions.like("resCode", resourceCode,MatchMode.START));
		}
		return super.getHibernateTemplate().findByCriteria(dc);
	}
	
	/**
	 * 根据角色及资源URL查询资源
	 * @param roles 角色集合
	 * @param resUrls 资源URL集合
	 * @return List<Resource>
	 */
	public List<Resource> findResourcesByRoleAndResUrl(Set<Long> roles , String[] resUrls){
		final DetachedCriteria dc = DetachedCriteria.forClass(Resource.class);
		dc.createAlias("roles", "rl").add(Restrictions.in("rl.roleId", roles));
		if(resUrls!=null && resUrls.length>0){
			dc.add(Restrictions.in("resUrl", resUrls));
		}
		return super.getHibernateTemplate().findByCriteria(dc);
	}
	

}
